package domain

import (
	"fmt"
	"gluenet/modules/manager/server/domain/aggregate"
	"gluenet/modules/manager/server/domain/vo"
	"gluenet/modules/manager/server/infra/prepare"
	"reflect"
)

func init() {
	//fmt.Printf("domina init\n")
	prepare.RegisterService(func() {
		domain := NewAgentDomain()
		prepare.InjectDependency(func() *Agent {
			return domain
		})
	})
}

type Agent struct {
	AgentFactory *aggregate.AgentFactory
}

func NewAgentDomain() *Agent {
	domain := &Agent{}
	prepare.FetchDependency(&domain.AgentFactory)
	return domain
}

func (r *Agent) UnRegister(guid string) error {
	return r.AgentFactory.UnRegister(guid)
}

func (r *Agent) Register(req vo.AgentRegisterReq) (*vo.AgentRegisterRes, error) {
	ag, err := r.AgentFactory.Register(req)
	if err != nil {
		return nil, err
	}
	return &vo.AgentRegisterRes{
		Guid:   ag.GUID,
		Config: ag.ConfigRepoValue,
	}, nil
}

func (r *Agent) GetConfig(guid string) (interface{}, error) {
	return r.AgentFactory.GetConfig(guid)
}

func (r *Agent) PutConfig(req vo.AgentPutConfigReq) error {
	return r.AgentFactory.PutConfig(req)
}

func (r *Agent) FindAll() (interface{}, error) {
	objs, err := r.AgentFactory.QueryAgentAll()
	if err != nil {
		return nil, err
	}
	return objs, nil
}

func (r *Agent) FindBy(query map[string]interface{}) (interface{}, error) {
	objs, err := r.AgentFactory.QueryAgent(query)
	if err != nil {
		return nil, err
	}
	return objs, nil
}

func (r *Agent) FindRuntime() (interface{}, error) {
	objs, err := r.AgentFactory.QueryAgentAll()
	if err != nil {
		return nil, fmt.Errorf("find agent %v", err)
	}
	var objRes = make([]interface{}, len(objs)+1)
	var tags []interface{}
	for k, v := range objs {
		res, err := v.ShowRuntime()
		if err != nil {
			return nil, err
		}
		area, err := r.AgentFactory.QueryArea(v.AreaID)
		if err != nil {
			return nil, fmt.Errorf("find area %v", err)
		}
		res.Area = area.City
		if k == 0 {
			e := reflect.TypeOf(res).Elem()
			num := e.NumField()
			tags = make([]interface{}, num)
			for i := 0; i < num; i++ {
				tags[i] = e.Field(i).Tag.Get(`json`)
			}
			objRes[0] = tags
		}
		var vals = make([]interface{}, len(tags))
		e := reflect.ValueOf(res).Elem()
		for fid := range tags {
			val := e.Field(fid).Interface()
			vals[fid] = val
		}
		objRes[k+1] = vals
	}
	return objRes, nil
}

func (r *Agent) FindRuntimeList() (interface{}, error) {
	objs, err := r.AgentFactory.QueryAgentAll()
	if err != nil {
		return nil, fmt.Errorf("find agent %v", err)
	}
	var objRes = make(map[string]interface{}, len(objs))
	for _, v := range objs {
		res, err := v.ShowRuntime()
		if err != nil {
			return nil, err
		}
		area, err := r.AgentFactory.QueryArea(v.AreaID)
		if err != nil {
			return nil, fmt.Errorf("find area %v", err)
		}
		res.Area = area.City

		objRes[res.GUID] = res
	}
	return objRes, nil
}

func (r *Agent) MarkedTag() {

}

func (r *Agent) CreateObject() {

}

func (r *Agent) RemoveObject() {

}

func (r *Agent) StartObject() {

}

func (r *Agent) StopObject() {

}

func (r *Agent) Configure() {

}
